﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using CFR.Silverlight.Core;
using System.Windows.Controls.Primitives;
using System.Collections.ObjectModel;


namespace CFR.Silverlight.Scheduling
{
    [TemplatePart(Name = "ViewContainer", Type = typeof(Panel))]
    public class Scheduler : Control
    {
        private Color _TodayBackgroundColor = Colors.White;

        public Color TodayBackgroundColor
        {
            get { return _TodayBackgroundColor; }
            set { _TodayBackgroundColor = value; }
        }


        #region Events
        public event EventHandler<CancelEventArgs> StartDateChanging;
        protected virtual void RaiseStartDateChanging(CancelEventArgs e)
        {
            if (StartDateChanging != null)
                StartDateChanging(this, e);
        }

        public event EventHandler StartDateChanged;
        protected virtual void RaiseStartDateChanged(EventArgs e)
        {
            if (StartDateChanged != null)
                StartDateChanged(this, e);
        }

        public event EventHandler<CancelEventArgs> EndDateChanging;
        protected virtual void RaiseEndDateChanging(CancelEventArgs e)
        {
            if (EndDateChanging != null)
                EndDateChanging(this, e);
        }

        public event EventHandler EndDateChanged;
        protected virtual void RaiseEndDateChanged(EventArgs e)
        {
            if (EndDateChanged != null)
                EndDateChanged(this, e);
        }

        public event EventHandler<EventItemEventArgs> EventItemClicked;
        protected internal virtual void RaiseEventItemClicked(EventItemEventArgs e)
        {
            if (EventItemClicked != null)
                EventItemClicked(this, e);
        }

        public event EventHandler<EventItemEventArgs> EventItemRightClicked;
        protected internal virtual void RaiseEventItemRightClicked(EventItemEventArgs e)
        {
            if (EventItemRightClicked != null)
                EventItemRightClicked(this, e);
        }

        public event EventHandler<EventItemEventArgs> EventItemMoved;
        protected internal virtual void RaiseEventItemMoved(EventItemEventArgs e)
        {
            if (EventItemMoved != null)
                EventItemMoved(this, e);
        }

        public event EventHandler<EventItemMovingEventArgs> EventItemMoving;
        protected internal virtual void RaiseEventItemMoving(EventItemMovingEventArgs e)
        {
            if (EventItemMoving != null)
                EventItemMoving(this, e);
        }

        public event EventHandler<EventItemEventArgs> EventHyperlinkClicked;
        protected internal virtual void RaiseEventHyperlinkClicked(EventItemEventArgs e)
        {
            if (EventHyperlinkClicked != null)
                EventHyperlinkClicked(this, e);
        }

        public event EventHandler<EventItemCreateEventArgs> CreatingEventItem;
        protected internal virtual void RaiseCreatingEventItem(EventItemCreateEventArgs e)
        {
            if (CreatingEventItem != null)
                CreatingEventItem(this, e);
        }
        #endregion

        #region Template Parts
        protected internal Border ViewContainer { get; private set; }
        protected internal ToggleButton DayButton { get; private set; }
        protected internal ToggleButton WeekButton { get; private set; }
        protected internal ToggleButton WeekdaysButton { get; private set; }
        protected internal ToggleButton MonthButton { get; private set; }
        protected internal ToggleButton AgendaButton { get; private set; }

        protected internal Button PreviousButton { get; private set; }
        protected internal Button TodayButton { get; private set; }
        protected internal Button NextButton { get; private set; }

        protected internal ToggleButton ToggleCalendarButton { get; private set; }
        protected internal ToggleButton ToggleCalendarListButton { get; private set; }
        protected internal StackPanel ViewButtonStackPanel { get; private set; }
        protected internal StackPanel CalendarListPanel { get; private set; }
        protected internal System.Windows.Controls.Calendar Calendar { get; private set; }
        protected internal ItemsControl CalendarsItemsControl { get; private set; }



        #endregion

        #region Events (DependencyProperty)

        /// <summary>
        /// Gets and sets the list of events for the scheduler for the given start and end dates
        /// </summary>
        public ObservableCollection<Event> Events
        {
            get { return (ObservableCollection<Event>)GetValue(EventsProperty); }
            set
            {
                SetValue(EventsProperty, value);
                SetContentForViewMode(true);
            }
        }
        public static readonly DependencyProperty EventsProperty =
            DependencyProperty.Register("Events", typeof(ObservableCollection<Event>), typeof(Scheduler),
            new PropertyMetadata(null, new PropertyChangedCallback(OnEventsChanged)));

        private static void OnEventsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {

            ((Scheduler)d).OnEventsChanged(e);
        }

        protected virtual void OnEventsChanged(DependencyPropertyChangedEventArgs e)
        {

        }



        #endregion

        #region ViewMode (DependencyProperty)

        /// <summary>
        /// Gets and sets the view mode for the scheduler.
        /// </summary>
        public ViewModes ViewMode
        {
            get { return (ViewModes)GetValue(ViewModeProperty); }
            set { SetValue(ViewModeProperty, value); }
        }

        public static readonly DependencyProperty ViewModeProperty =
            DependencyProperty.Register("ViewMode", typeof(ViewModes), typeof(Scheduler),
            new PropertyMetadata(ViewModes.WholeWeek, new PropertyChangedCallback(OnViewModeChanged)));

        private static void OnViewModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Scheduler)d).OnViewModeChanged(e);
        }

        protected virtual void OnViewModeChanged(DependencyPropertyChangedEventArgs e)
        {
            SetContentForViewMode(false);
        }

        #endregion
        #region StartDate (DependencyProperty)

        /// <summary>
        /// Gets and sets the start date for the scheduler
        /// </summary>
        public DateTime StartDate
        {
            get { return (DateTime)GetValue(StartDateProperty); }
            set
            {

                CancelEventArgs e = new CancelEventArgs();

                RaiseStartDateChanging(e);

                if (!e.Cancel)
                {
                    SetValue(StartDateProperty, value);
                    ShortStartDate = value.ToString("DDD dd/yy");

                }
            }

        }
        public static readonly DependencyProperty StartDateProperty =
            DependencyProperty.Register("StartDate", typeof(DateTime), typeof(Scheduler),
            new PropertyMetadata(DateTime.Now.Date, new PropertyChangedCallback(OnStartDateChanged)));

        private static void OnStartDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Scheduler)d).Calendar.DisplayDate = (DateTime)e.NewValue;
            ((Scheduler)d).RaiseStartDateChanged(EventArgs.Empty);
        }


        #endregion
        #region EndDate (DependencyProperty)

        /// <summary>
        /// Gets and sets the end date for the scheduler
        /// </summary>
        public DateTime? EndDate
        {
            get { return (DateTime?)GetValue(EndDateProperty); }
            set
            {
                CancelEventArgs e = new CancelEventArgs();

                RaiseEndDateChanging(e);

                if (!e.Cancel)
                {
                    SetValue(EndDateProperty, value);
                    if (value.HasValue)
                    {
                        ShortEndDate = value.Value.ToString("DDD dd/yy");
                    }
                }

            }
        }
        public static readonly DependencyProperty EndDateProperty =
            DependencyProperty.Register("EndDate", typeof(DateTime?), typeof(Scheduler),
            new PropertyMetadata(null, new PropertyChangedCallback(OnEndDateChanged)));

        private static void OnEndDateChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ((Scheduler)d).RefreshCurrentView();
            ((Scheduler)d).RaiseEndDateChanged(EventArgs.Empty);
        }





        #endregion

        #region ShortStartDate (DependencyProperty)

        /// <summary>
        /// Gets the Start Date in a short format.
        /// </summary>
        internal string ShortStartDate
        {
            get { return (string)GetValue(ShortStartDateProperty); }
            set { SetValue(ShortStartDateProperty, value); }
        }
        public static readonly DependencyProperty ShortStartDateProperty =
            DependencyProperty.Register("ShortStartDate", typeof(string), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion
        #region ShortEndDate (DependencyProperty)

        /// <summary>
        /// Gets or sets the End Date in short format.
        /// </summary>
        internal string ShortEndDate
        {
            get { return (string)GetValue(ShortEndDateProperty); }
            set { SetValue(ShortEndDateProperty, value); }
        }
        public static readonly DependencyProperty ShortEndDateProperty =
            DependencyProperty.Register("ShortEndDate", typeof(string), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion

        #region ViewButtonStyle (DependencyProperty)

        /// <summary>
        /// Gets or sets the style used for the View buttons
        /// </summary>
        public Style ViewButtonStyle
        {
            get { return (Style)GetValue(ViewButtonStyleProperty); }
            set { SetValue(ViewButtonStyleProperty, value); }
        }
        public static readonly DependencyProperty ViewButtonStyleProperty =
            DependencyProperty.Register("ViewButtonStyle", typeof(Style), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion

        #region ToggleCalendarVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the Calendar Show/Hide Toggle button.
        /// </summary>
        public Visibility ToggleCalendarVisibility
        {
            get { return (Visibility)GetValue(ToggleCalendarVisibilityProperty); }
            set { SetValue(ToggleCalendarVisibilityProperty, value); }
        }
        public static readonly DependencyProperty ToggleCalendarVisibilityProperty =
            DependencyProperty.Register("ToggleCalendarVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion

        #region CalendarVisibility (DependencyProperty)

        /// <summary>
        /// Gets or set the visibility for the selection calendar
        /// </summary>
        public Visibility CalendarVisibility
        {
            get { return (Visibility)GetValue(CalendarVisibilityProperty); }
            set { SetValue(CalendarVisibilityProperty, value); }
        }
        public static readonly DependencyProperty CalendarVisibilityProperty =
            DependencyProperty.Register("CalendarVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion
        #region CalendarSelectorVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility for the calendar selector
        /// </summary>
        public Visibility CalendarSelectorVisibility
        {
            get { return (Visibility)GetValue(CalendarSelectorVisibilityProperty); }
            set { SetValue(CalendarSelectorVisibilityProperty, value); }
        }
        public static readonly DependencyProperty CalendarSelectorVisibilityProperty =
            DependencyProperty.Register("CalendarSelectorVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion

        #region CalendarsTitleText (DependencyProperty)

        /// <summary>
        /// Gets or sets the title text for the Calendars section
        /// </summary>
        public string CalendarsTitleText
        {
            get { return (string)GetValue(CalendarsTitleTextProperty); }
            set { SetValue(CalendarsTitleTextProperty, value); }
        }
        public static readonly DependencyProperty CalendarsTitleTextProperty =
            DependencyProperty.Register("CalendarsTitleText", typeof(string), typeof(Scheduler),
              new PropertyMetadata("Calendars"));

        #endregion

        #region AgendaTabVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the agenda button.
        /// </summary>
        public Visibility AgendaTabVisibility
        {
            get { return (Visibility)GetValue(AgendaTabVisibilityProperty); }
            set { SetValue(AgendaTabVisibilityProperty, value); }
        }
        public static readonly DependencyProperty AgendaTabVisibilityProperty =
            DependencyProperty.Register("AgendaTabVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion
        #region MonthTabVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the Month tab.
        /// </summary>
        public Visibility MonthTabVisibility
        {
            get { return (Visibility)GetValue(MonthTabVisibilityProperty); }
            set { SetValue(MonthTabVisibilityProperty, value); }
        }
        public static readonly DependencyProperty MonthTabVisibilityProperty =
            DependencyProperty.Register("MonthTabVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion
        #region WeekdaysTabVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the Weekdays tab
        /// </summary>
        public Visibility WeekdaysTabVisibility
        {
            get { return (Visibility)GetValue(WeekdaysTabVisibilityProperty); }
            set { SetValue(WeekdaysTabVisibilityProperty, value); }
        }
        public static readonly DependencyProperty WeekdaysTabVisibilityProperty =
            DependencyProperty.Register("WeekdaysTabVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion
        #region WeekTabVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the Week tab
        /// </summary>
        public Visibility WeekTabVisibility
        {
            get { return (Visibility)GetValue(WeekTabVisibilityProperty); }
            set { SetValue(WeekTabVisibilityProperty, value); }
        }
        public static readonly DependencyProperty WeekTabVisibilityProperty =
            DependencyProperty.Register("WeekTabVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion
        #region DayTabVisibility (DependencyProperty)

        /// <summary>
        /// Gets or sets the visibility of the Day tab
        /// </summary>
        public Visibility DayTabVisibility
        {
            get { return (Visibility)GetValue(DayTabVisibilityProperty); }
            set { SetValue(DayTabVisibilityProperty, value); }
        }
        public static readonly DependencyProperty DayTabVisibilityProperty =
            DependencyProperty.Register("DayTabVisibility", typeof(Visibility), typeof(Scheduler),
              new PropertyMetadata(Visibility.Visible));

        #endregion


        #region EventTooltip (DependencyProperty)

        /// <summary>
        /// Gets and sets the tooltip used for the event items.
        /// </summary>
        public DataTemplate EventTooltip
        {
            get { return (DataTemplate)GetValue(EventTooltipProperty); }
            set { SetValue(EventTooltipProperty, value); }
        }
        public static readonly DependencyProperty EventTooltipProperty =
            DependencyProperty.Register("EventTooltip", typeof(DataTemplate), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion
        #region AllDayEventTooltip (DependencyProperty)

        /// <summary>
        /// Gets and sets the tooltip used for the all-day event items
        /// </summary>
        public DataTemplate AllDayEventTooltip
        {
            get { return (DataTemplate)GetValue(AllDayEventTooltipProperty); }
            set { SetValue(AllDayEventTooltipProperty, value); }
        }
        public static readonly DependencyProperty AllDayEventTooltipProperty =
            DependencyProperty.Register("AllDayEventTooltip", typeof(DataTemplate), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion


        #region Calendars (DependencyProperty)

        /// <summary>
        /// Gets or sets the list of calendars for the schedule.
        /// </summary>
        public IEnumerable<Calendar> Calendars
        {
            get { return (IEnumerable<Calendar>)GetValue(CalendarsProperty); }
            set
            {
                SetValue(CalendarsProperty, value);

                foreach (Calendar c in value)
                    c.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(calendar_PropertyChanged);
            }
        }


        public static readonly DependencyProperty CalendarsProperty =
            DependencyProperty.Register("Calendars", typeof(IEnumerable<Calendar>), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion


        #region ScheduleBackground (DependencyProperty)

        /// <summary>
        /// Gets or sets the background brush for the scheduling area
        /// </summary>
        public Brush ScheduleBackground
        {
            get { return (Brush)GetValue(ScheduleBackgroundProperty); }
            set { SetValue(ScheduleBackgroundProperty, value); }
        }
        public static readonly DependencyProperty ScheduleBackgroundProperty =
            DependencyProperty.Register("ScheduleBackground", typeof(Brush), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion

        public ViewBase CurrentView
        {
            get
            {

                if (ViewContainer == null)
                    return null;
                return ViewContainer.Child as ViewBase;
            }
        }


        #region EventTitleContentTemplate (DependencyProperty)

        /// <summary>
        /// Gets or sets the Content Template used for the title section of events
        /// </summary>
        public DataTemplate EventTitleContentTemplate
        {
            get { return (DataTemplate)GetValue(EventTitleContentTemplateProperty); }
            set { SetValue(EventTitleContentTemplateProperty, value); }
        }
        public static readonly DependencyProperty EventTitleContentTemplateProperty =
            DependencyProperty.Register("EventTitleContentTemplate", typeof(DataTemplate), typeof(Scheduler),
              new PropertyMetadata(null));

        #endregion


        /// <summary>
        /// The number of days to show on the Agenda tab.
        /// </summary>
        private int _agendaDayCount = 7;

        public int AgendaDayCount
        {
            get { return _agendaDayCount; }
            set
            {
                _agendaDayCount = value;

                if (CurrentView != null && CurrentView is AgendaView)
                    CurrentView.Refresh();
            }
        }


        public Scheduler()
        {
            this.DefaultStyleKey = typeof(Scheduler);
            this.Events = new ObservableCollection<Event>();

            this.Loaded += new RoutedEventHandler(Scheduler_Loaded);
        }

        void Scheduler_Loaded(object sender, RoutedEventArgs e)
        {

        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();

            ViewContainer = (Border)GetTemplateChild("ViewContainer");
            ViewButtonStackPanel = (StackPanel)GetTemplateChild("ViewButtonStackPanel");
            DayButton = (ToggleButton)GetTemplateChild("DayButton");
            WeekButton = (ToggleButton)GetTemplateChild("WeekButton");
            WeekdaysButton = (ToggleButton)GetTemplateChild("WeekdaysButton");
            MonthButton = (ToggleButton)GetTemplateChild("MonthButton");
            AgendaButton = (ToggleButton)GetTemplateChild("AgendaButton");
            Calendar = (System.Windows.Controls.Calendar)GetTemplateChild("Calendar");
            ToggleCalendarButton = (ToggleButton)GetTemplateChild("ToggleCalendarButton");
            ToggleCalendarListButton = (ToggleButton)GetTemplateChild("ToggleCalendarListButton");
            CalendarListPanel = (StackPanel)GetTemplateChild("CalendarListPanel");
            CalendarsItemsControl = (ItemsControl)GetTemplateChild("CalendarsItemsControl");

            PreviousButton = (Button)GetTemplateChild("PreviousButton");
            TodayButton = (Button)GetTemplateChild("TodayButton");
            NextButton = (Button)GetTemplateChild("NextButton");

            SetContentForViewMode(true);

            PreviousButton.Click += new RoutedEventHandler(PreviousButton_Click);
            TodayButton.Click += new RoutedEventHandler(TodayButton_Click);
            NextButton.Click += new RoutedEventHandler(NextButton_Click);

            DayButton.Checked += new RoutedEventHandler(DayButton_Checked);
            DayButton.Unchecked += new RoutedEventHandler(DayButton_Unchecked);
            WeekButton.Checked += new RoutedEventHandler(WeekButton_Checked);
            WeekButton.Unchecked += new RoutedEventHandler(WeekButton_Unchecked);
            WeekdaysButton.Checked += new RoutedEventHandler(WeekdaysButton_Checked);
            WeekdaysButton.Unchecked += new RoutedEventHandler(WeekdaysButton_Unchecked);
            MonthButton.Checked += new RoutedEventHandler(MonthButton_Checked);
            MonthButton.Unchecked += new RoutedEventHandler(MonthButton_Unchecked);
            AgendaButton.Checked += new RoutedEventHandler(AgendaButton_Checked);
            AgendaButton.Unchecked += new RoutedEventHandler(AgendaButton_Unchecked);

            Calendar.SelectedDatesChanged += new EventHandler<SelectionChangedEventArgs>(Calendar_SelectedDatesChanged);

            ToggleCalendarButton.Checked += new RoutedEventHandler(ToggleCalendarButton_Checked);
            ToggleCalendarButton.Unchecked += new RoutedEventHandler(ToggleCalendarButton_Unchecked);
            ToggleCalendarListButton.Checked += new RoutedEventHandler(ToggleCalendarListButton_Checked);
            ToggleCalendarListButton.Unchecked += new RoutedEventHandler(ToggleCalendarListButton_Unchecked);


        }

  
        void calendar_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsShownInScheduler")
                CurrentView.Refresh();
        }
        void NextButton_Click(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.WeekDays)
                Calendar.SelectedDate = Calendar.SelectedDates.Max().AddDays(2);
            else if(ViewMode == ViewModes.Agenda)
                Calendar.SelectedDate = Calendar.SelectedDates.Min().AddDays(1);     
            else
                Calendar.SelectedDate = Calendar.SelectedDates.Max().AddDays(1);

        }

        void TodayButton_Click(object sender, RoutedEventArgs e)
        {
            Calendar.SelectedDate = DateTime.Now;

        }

        void PreviousButton_Click(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.WeekDays)
                Calendar.SelectedDate = Calendar.SelectedDates.Min().AddDays(-2);
            else
                Calendar.SelectedDate = Calendar.SelectedDates.Min().AddDays(-1);
        }

        void ToggleCalendarListButton_Unchecked(object sender, RoutedEventArgs e)
        {
            CalendarListPanel.Visibility = System.Windows.Visibility.Collapsed;
            ToggleCalendarListButton.Content = "<";
        }

        void ToggleCalendarListButton_Checked(object sender, RoutedEventArgs e)
        {
            CalendarListPanel.Visibility = System.Windows.Visibility.Visible;
            ToggleCalendarListButton.Content = ">";

        }

        void ToggleCalendarButton_Unchecked(object sender, RoutedEventArgs e)
        {
            Calendar.Visibility = System.Windows.Visibility.Collapsed;
            ToggleCalendarButton.Content = "<";
        }

        void ToggleCalendarButton_Checked(object sender, RoutedEventArgs e)
        {
            Calendar.Visibility = System.Windows.Visibility.Visible;
            ToggleCalendarButton.Content = ">";

        }




        bool _skipSelectedDatesUpdates = false;

        void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e)
        {
            if (_skipSelectedDatesUpdates || Calendar.SelectedDates.Count == 0)
                return;

            UpdateCalendarSelectedDates();

            ResetStartAndEndDate();


        }

        private void ResetStartAndEndDate()
        {
            StartDate = Calendar.SelectedDates.Min();
            EndDate = Calendar.SelectedDates.Max();
        }

        internal void UpdateCalendarSelectedDates()
        {
            _skipSelectedDatesUpdates = true;
            if (ViewMode == ViewModes.WeekDays || ViewMode == ViewModes.WholeWeek)
            {
                if (Calendar.SelectedDate == null)
                    Calendar.SelectedDate = DateTime.Now.Date;
                else
                    Calendar.SelectedDate = Calendar.SelectedDates.Min().Date;

                DateTime firstDayOfWeek = Calendar.SelectedDate.Value.AddDays(-(int)Calendar.SelectedDates.Min().DayOfWeek);

                Calendar.SelectedDates.Clear();

                if (ViewMode == ViewModes.WholeWeek)
                    Calendar.SelectedDates.AddRange(firstDayOfWeek, firstDayOfWeek.AddDays(6));
                else
                    Calendar.SelectedDates.AddRange(firstDayOfWeek.AddDays(1), firstDayOfWeek.AddDays(5));



            }
            else if (ViewMode == ViewModes.Day)
            {
                if (Calendar.SelectedDate == null)
                    Calendar.SelectedDate = DateTime.Now.Date;
                else
                    Calendar.SelectedDate = Calendar.SelectedDates.Min().Date;

            }
            else if (ViewMode == ViewModes.Agenda)
            {
                if (Calendar.SelectedDate == null)
                    Calendar.SelectedDate = DateTime.Now.Date;
                else
                    Calendar.SelectedDate = Calendar.SelectedDates.Min().Date;

                var firstDay = Calendar.SelectedDate;

                Calendar.SelectedDates.Clear();

                Calendar.SelectedDates.AddRange(firstDay.Value, firstDay.Value.AddDays(AgendaDayCount - 1));
            }
            else if (ViewMode == ViewModes.Month)
            {
                if (Calendar.SelectedDate == null || Calendar.SelectedDates.Count == 0)
                    Calendar.SelectedDate = DateTime.Now.Date;
                else
                    Calendar.SelectedDate = Calendar.SelectedDates.Min().Date;


                DateTime firstDayOfMonth = Calendar.SelectedDate.Value.AddDays(-Calendar.SelectedDate.Value.Day + 1);

                Calendar.SelectedDates.Clear();

                Calendar.SelectedDates.AddRange(firstDayOfMonth,
                        firstDayOfMonth.AddDays(DateTime.DaysInMonth(firstDayOfMonth.Year, firstDayOfMonth.Month) - 1));
            }

            ResetStartAndEndDate();
            _skipSelectedDatesUpdates = false;
        }

        #region View Button Events
        void AgendaButton_Checked(object sender, RoutedEventArgs e)
        {
            ViewMode = ViewModes.Agenda;
            UncheckOtherButtons(sender);
        }
        void AgendaButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.Agenda)
                AgendaButton.IsChecked = true;
        }

        void MonthButton_Checked(object sender, RoutedEventArgs e)
        {
            ViewMode = ViewModes.Month;
            UncheckOtherButtons(sender);
        }
        void MonthButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.Month)
                MonthButton.IsChecked = true;
        }

        void WeekdaysButton_Checked(object sender, RoutedEventArgs e)
        {
            ViewMode = ViewModes.WeekDays;
            UncheckOtherButtons(sender);
        }
        void WeekdaysButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.WeekDays)
                WeekdaysButton.IsChecked = true;
        }

        void WeekButton_Checked(object sender, RoutedEventArgs e)
        {
            ViewMode = ViewModes.WholeWeek;
            UncheckOtherButtons(sender);

        }
        void WeekButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.WholeWeek)
                WeekButton.IsChecked = true;
        }

        void DayButton_Checked(object sender, RoutedEventArgs e)
        {
            ViewMode = ViewModes.Day;
            UncheckOtherButtons(sender);
        }
        void DayButton_Unchecked(object sender, RoutedEventArgs e)
        {
            if (ViewMode == ViewModes.Day)
                DayButton.IsChecked = true;
        }
        #endregion

        private void UncheckOtherButtons(object sender)
        {
            foreach (ToggleButton tb in ViewButtonStackPanel.Children)
            {
                if (tb != sender)
                {
                    tb.IsChecked = false;
                }
            }
        }
        private void SetContentForViewMode(bool updateCalendar)
        {
            if (ViewContainer == null)
                return;


            switch (ViewMode)
            {
                case ViewModes.Agenda:
                    Calendar.SelectionMode = CalendarSelectionMode.SingleRange;

                    if (ViewContainer.Child is AgendaView)
                        (ViewContainer.Child as AgendaView).Refresh();
                    else
                        ViewContainer.Child = new AgendaView(this);

                    if (AgendaButton.IsChecked == false)
                        AgendaButton.IsChecked = true;

                    break;
                case ViewModes.Day:
                    Calendar.SelectionMode = CalendarSelectionMode.SingleDate;

                    if (ViewContainer.Child is DayView)
                        (ViewContainer.Child as DayView).Refresh();
                    else
                        ViewContainer.Child = new DayView(this);

                    if (DayButton.IsChecked == false)
                        DayButton.IsChecked = true;

                    break;
                case ViewModes.Month:
                    Calendar.SelectionMode = CalendarSelectionMode.SingleRange;
                    
                    if(ViewContainer.Child is MonthView)
                        (ViewContainer.Child as MonthView).Refresh();
                    else
                        ViewContainer.Child = new MonthView(this);


                    if (MonthButton.IsChecked == false)
                        MonthButton.IsChecked = true;

                    break;
                case ViewModes.WeekDays:
                    Calendar.SelectionMode = CalendarSelectionMode.SingleRange;

                    if (ViewContainer.Child is DayView)
                        (ViewContainer.Child as DayView).Refresh();
                    else
                        ViewContainer.Child = new DayView(this);

                    if (WeekdaysButton.IsChecked == false)
                        WeekdaysButton.IsChecked = true;

                    break;
                case ViewModes.WholeWeek:
                default:
                    Calendar.SelectionMode = CalendarSelectionMode.SingleRange;

                    if (ViewContainer.Child is DayView)
                        (ViewContainer.Child as DayView).Refresh();
                    else
                        ViewContainer.Child = new DayView(this);

                    if (WeekButton.IsChecked == false)
                        WeekButton.IsChecked = true;

                    break;

            }

            UpdateCalendarSelectedDates();


        }
        private void RefreshCurrentView()
        {
            if (CurrentView != null)
                CurrentView.Refresh();
        }

    }
}
